package com.mallcloud.mall.mall.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.app.mapper.AppProcedureMapper;
import com.mallcloud.mall.common.core.constant.enums.RLockEnum;
import com.mallcloud.mall.common.core.exception.FailException;
import com.mallcloud.mall.mall.api.entity.MallValueCardModel;
import com.mallcloud.mall.mall.api.entity.dto.*;
import com.mallcloud.mall.mall.mapper.MallValueCardMapper;
import com.mallcloud.mall.mall.service.MallValueCardService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * 储值卡管理 服务实现类
 */
@Slf4j
@Service
@AllArgsConstructor
public class MallValueCardServiceImpl extends ServiceImpl<MallValueCardMapper, MallValueCardModel> implements MallValueCardService {
	private final AppProcedureMapper procedureMapper;
	private final Redisson redisson;

	@SneakyThrows
	@Override
	public ProValueCardPurchase buy(ProValueCardPurchase entity) {
		log.info("购买储值卡请求锁");
		RLock lock = redisson.getLock(RLockEnum.VALUE_CARD_PURCHASE.getKey(entity.getValueCardMainId()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.buy(entity);
			if(!entity.isSuccess()) {
				log.error("失败");
				throw new FailException(entity.getMessage());
			}
			return entity;
		}
		finally {
			lock.unlock();
		}

	}

	@SneakyThrows
	@Override
	public BigDecimal recharge(ProValueCardRecharge entity) {
		log.info("储值卡充值请求锁");
		RLock lock = redisson.getLock(RLockEnum.VALUE_CARD_RECHARGE.getKey(entity.getCardNo()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.recharge(entity);
			if(!entity.isSuccess()) {
				throw new FailException(entity.getMessage());
			}
			return entity.getStoredValueAmount();
		}
		finally {
			lock.unlock();
		}
	}

	@SneakyThrows
	@Override
	public void bind(ProValueCardBind entity) {
		log.info("储值卡绑定请求锁");
		RLock lock = redisson.getLock(RLockEnum.VALUE_CARD_BIND.getKey(entity.getBindCardNo()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.bind(entity);
			if(!entity.isSuccess()) {
				log.error("失败");
				throw new FailException(entity.getMessage());
			}
		}
		finally {
			lock.unlock();
		}
	}

	@SneakyThrows
	@Override
	public void given(ProValueCardGiven entity) {
		log.info("储值卡转赠请求锁");
		RLock lock = redisson.getLock(RLockEnum.VALUE_CARD_GIVEN.getKey(entity.getCardNo()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.given(entity);
			if(!entity.isSuccess()) {
				log.error("失败");
				throw new FailException(entity.getMessage());
			}
		}
		finally {
			lock.unlock();
		}

	}

	@SneakyThrows
	@Override
	public void givenStatus(ProValueCardGivenStatus entity) {
		RLock lock = redisson.getLock(RLockEnum.VALUE_CARD_GIVEN.getKey(entity.getMsgId()));
		lock.lock(10, TimeUnit.SECONDS);
		try {
			procedureMapper.givenStatus(entity);
			if(!entity.isSuccess()) {
				log.error("失败");
				throw new FailException(entity.getMessage());
			}
		}
		finally {
			lock.unlock();
		}

	}
}
